class: center, middle, inverse, title-slide # Introducción a R - Sesión 1 ## Un curso (bastante) rápido ### Octavio Medina ### 2021-11-24 --- --- class: center middle # Lo que cubriremos hoy --- ## Sesión 1 - Qué es **R** y en qué se parece a Stata y otras opciones? - Puntos **básicos**: objetos y `dataframes`! - Leer y **modificar** datos - Correr regresiones y presentar resultados ## Sesión 2 - AnatomÃa de una gráfica: el *grammar of graphics* - Visualizar datos con `ggplot2` - Visualizar modelos con `ggplot2` --- class: inverse center middle # Sesión 1: 10-11.30am --- # Qué es R? - R fue creado como lenguaje de programación para estadÃstica y gráficos, pero se ha convertido en mucho más que eso. - En principio es similar a Stata y otros programas de computación estadÃstica como SPSS o SAS. PERO hay un número de cosas que lo diferencian. -- .panelset[ .panel[.panel-name[Cosas parecidas] ### Cosas parecidas - Abres bases de datos - Creas variables, las modificas - Analizas datos - Reportas resultados ] .panel[.panel-name[Cosas diferentes] ### Cosas diferentes - Muchos tipos de objetos (y múltiples bases!) - Es un lenguaje de programación - Flexibilidad (y diversidad) - Sinergias e interés compuesto ] ] --- ## Ejemplo: Profundidad y longitud del pico en pingüinos
--- class: center middle ## Y qué pasa con RStudio? Rstudio es el IDE (entorno de desarrollo integrado) más utilizado para programar con R. Enlace para descargar: https://www.rstudio.com/products/rstudio/download/ --- ## Antes de empezar `R` utiliza muchos paquetes. Los paquetes **expanden el universo de cosas** que se pueden hacer con `R`, a menudo de manera espectacular. - Para simplificar las cosas, solo instalaremos cuatro paquetes: la familia de paquetes `tidyverse`,`gapminder` (que usaremos para explorar la base de datos del mismo nombre), `broom` y `modelsummary`. - En las próximas sesiones también utilizaremos la ECV, para asà usar datos similares a los que habitualmente utilizamos. - Para instalarlos, simplemente tenemos que ejecutar estos dos comandos en la consola: ```r install.packages("tidyverse") install.packages("gapminder") install.packages("broom") install.packages("modelsummary") ``` --- ## Antes de empezar - Solo necesitamos instalar los paquetes una vez en cada ordenador. Una vez hecho, podemos cargarlos cuando lo necesitemos (generalmente al principio de la sesión). ```r library(tidyverse) library(gapminder) ``` --- # Lo primero: el operador de asignación - R está **lleno de objetos** - Para guardar un objeto, usamos el **operador de asignación** (`<-`) - También podemos utilizar el `=`, pero se usa menos ```r mi_variable <- 2021 mi_nombre <- "KSNET" ``` - Para imprimir un objeto, vale con ponerlo en la consola como si fuera un comando: ```r mi_nombre ``` ``` ## [1] "KSNET" ``` --- # Tipos de objetos La estructura de datos más básica en R es un vector. - Los vectores tienen **una dimensión** (son como una lÃnea) - Los vectores pueden ser **numéricos**, **caracteres**, **lógicos** ... - Pero ojo, todos deben compartir el mismo tipo! Aquà hay unos ejemplos: ```r # Podemos crear un vector usando el operador de asignación (<-) my_letters <- c("a", "b", "c") my_numbers <- c(1,2,3) # Ahora veamos qué pasa si mezclamos tipos all_mixed <- c("a", 2, "b", 3) ``` --- ## Varios vectores = una base de datos - En R las bases de datos se llaman `dataframes` - ¿Y qué es una base de datos? Es un montón de **vectores** junntos, unidos verticalmente. ```r oveja_nombre <- c("Molly", "Polly", "Dolly") oveja_peso <- c(120, 90, 85) oveja_edad <- c(3,4,2) mis_ovejas <- data.frame(oveja_nombre, oveja_peso, oveja_edad) ``` Vamos a imprimirlo para verlo: ```r mis_ovejas ``` ``` ## oveja_nombre oveja_peso oveja_edad ## 1 Molly 120 3 ## 2 Polly 90 4 ## 3 Dolly 85 2 ``` --- ## Importación y manipulación de datos - No siempre creamos `dataframes` de esta manera, pero es útil como **modelo mental**. - Por lo general, hacemos lo mismo que en Stata, y **abrimos o leemos** los datos. - Para hacer eso, usaremos la familia de funciones `read_ *` disponibles como parte del `tidyverse`. Hay un ejemplo en vuestro script, para verlo después del training. - Para esta sesión, usaremos la base de datos `gapminder`, que podemos abrir usando `data (gapminder)`, ya que ya viene instalada con el paquete del mismo nombre. ```r data(gapminder) ``` Lo podéis ver? --- ## Hablemos de gramática y verbos Para manipular datos utilizaremos los verbos del paquete `dplyr`, parte de la familia del `tidyverse`. Hay varios verbos disponibles para la manipulación de datos. Hoy le echaremos un vistazo a estos: - `select()` - `filter()` - `mutate()` - `arrange()` - `summarize()` - `group_by()` Con estas 6 herramientas, deberÃais poder hacer aproximadamente el 80% de las tareas de manipulación de datos. --- class: inverse center middle ### Para el otro 20%: Google y Stackoverflow son tus mejores amigos.  --- ## Echando un vistazo a los datos Echemos un vistazo a nuestro conjunto de datos. Puedes mirar las primeras 5 observaciones usando `head()`: ```r head(gapminder) ``` ``` ## # A tibble: 6 × 6 ## country continent year lifeExp pop gdpPercap ## <fct> <fct> <int> <dbl> <int> <dbl> ## 1 Afghanistan Asia 1952 28.8 8425333 779. ## 2 Afghanistan Asia 1957 30.3 9240934 821. ## 3 Afghanistan Asia 1962 32.0 10267083 853. ## 4 Afghanistan Asia 1967 34.0 11537966 836. ## 5 Afghanistan Asia 1972 36.1 13079460 740. ## 6 Afghanistan Asia 1977 38.4 14880372 786. ``` --- ## Echando un vistazo a los datos También se puede usar `summary()` para obtener una descripción general de la base de datos. Esto es similar al comando `summarize` de Stata: ```r summary(gapminder) ``` ``` ## country continent year lifeExp ## Afghanistan: 12 Africa :624 Min. :1952 Min. :23.60 ## Albania : 12 Americas:300 1st Qu.:1966 1st Qu.:48.20 ## Algeria : 12 Asia :396 Median :1980 Median :60.71 ## Angola : 12 Europe :360 Mean :1980 Mean :59.47 ## Argentina : 12 Oceania : 24 3rd Qu.:1993 3rd Qu.:70.85 ## Australia : 12 Max. :2007 Max. :82.60 ## (Other) :1632 ## pop gdpPercap ## Min. :6.001e+04 Min. : 241.2 ## 1st Qu.:2.794e+06 1st Qu.: 1202.1 ## Median :7.024e+06 Median : 3531.8 ## Mean :2.960e+07 Mean : 7215.3 ## 3rd Qu.:1.959e+07 3rd Qu.: 9325.5 ## Max. :1.319e+09 Max. :113523.1 ## ``` --- ## Echando un vistazo a los datos Finalmente, podemos utilizar `table()` como sustituto de `tab` en Stata. Esto es particularmente útil para variables categóricas. Por ejemplo, el # de observaciones por continente. Ojo porque tendremos que usar el sÃmbolo `$` para especificar qué variable queremos tabular (porque en R se pueden tener varios dataframes de forma simultánea). ```r table(gapminder$continent) ``` ``` ## ## Africa Americas Asia Europe Oceania ## 624 300 396 360 24 ``` --- ## Seleccionar variables y filtrar observaciones Usamos `select` para seleccionar **variables**, y` filter` para filtrar **observaciones**. Una ventaja de R es que no tenemos que renunciar a nuestro dataframe original! Simplemente podemos crear un **objeto nuevo** o **actualizar uno anterior.** Ok, vamos a conservar solo las variables `country`,` year` y `lifeExp`. ```r df_redux <- select(gapminder, country, year, lifeExp) head(df_redux) ``` ``` ## # A tibble: 6 × 3 ## country year lifeExp ## <fct> <int> <dbl> ## 1 Afghanistan 1952 28.8 ## 2 Afghanistan 1957 30.3 ## 3 Afghanistan 1962 32.0 ## 4 Afghanistan 1967 34.0 ## 5 Afghanistan 1972 36.1 ## 6 Afghanistan 1977 38.4 ``` --- ## Seleccionar variables y filtrar observaciones Ahora intentemos usar `filter ()`. Se puede filtrar por cualquier condición! Aquà filtraremos por año y paÃs. ```r df_filtered <- filter(gapminder, year == 1957, country == "Belgium") df_filtered ``` ``` ## # A tibble: 1 × 6 ## country continent year lifeExp pop gdpPercap ## <fct> <fct> <int> <dbl> <int> <dbl> ## 1 Belgium Europe 1957 69.2 8989111 9715. ``` --- ## Hacer todo a la vez es mejor .pull-left[ - El `pipe` (o tuberÃa) es un invento estupendo: `%>%` - Conceptualmente, es como decir "... y luego ..." - El `pipe` nos permite encadenar operaciones y nos facilitará la vida - Ahora vamos a filtrar por continente y año, y manteniendo tres variables: ```r gapminder %>% filter(continent == "Oceania", year == 2007) %>% select(continent, country, lifeExp) ``` ``` ## # A tibble: 2 × 3 ## continent country lifeExp ## <fct> <fct> <dbl> ## 1 Oceania Australia 81.2 ## 2 Oceania New Zealand 80.2 ``` ] .pull-right[ <div class="figure" style="text-align: center"> <img src="data:image/png;base64,#pipe.jpeg" alt="This is not a pipe." width="70%" /> <p class="caption">This is not a pipe.</p> </div> ] --- ## Referencia: `select()` Seleccionar por nombre de columna: ```r gapminder %>% select(country) ``` Seleccionar por posición de columna: ```r gapminder %>% select(1:2) ``` Todas las columnas menos la primera: ```r gapminder %>% select(-1) ``` --- ## Referencia: `filter()` Se pueden combinar varias expresiones con una coma o `&`: ```r gapminder %>% filter(continent == "Europe" & year == 2007) ``` Podemos utilizar el operador `|` cuando queramos un `o` en vez de `y`: ```r gapminder %>% filter(continent == "Europe" | continent == "Americas") ``` Un signo de exclamación niega una condición. Para mantener todas las **observaciones que no faltan (NA)**, podemos poner: ```r gapminder %>% filter(!is.na(continent)) ``` --- ## Mutar para crear (o cambiar) variables - Podemos usar el verbo `mutate ()` para crear o modificar variables usando todas las operaciones comunes (por ejemplo, sumar, restar, multiplicar, dividir...). - Si os fijáis, en nuestros datos no hay variable de PIB! Creámosla multiplicando el PIB per cápita por la población y guardemos el resultado como un nuevo dataframe. ```r df_gdp <- gapminder %>% mutate(gdp = pop * gdpPercap) head(df_gdp) ``` ``` ## # A tibble: 6 × 7 ## country continent year lifeExp pop gdpPercap gdp ## <fct> <fct> <int> <dbl> <int> <dbl> <dbl> ## 1 Afghanistan Asia 1952 28.8 8425333 779. 6567086330. ## 2 Afghanistan Asia 1957 30.3 9240934 821. 7585448670. ## 3 Afghanistan Asia 1962 32.0 10267083 853. 8758855797. ## 4 Afghanistan Asia 1967 34.0 11537966 836. 9648014150. ## 5 Afghanistan Asia 1972 36.1 13079460 740. 9678553274. ## 6 Afghanistan Asia 1977 38.4 14880372 786. 11697659231. ``` --- ## Mutar para crear (o cambiar) variables Ok, eso es bastante grande. También podrÃamos dividirlo por 1,000,000 para tenerlo en millones de dólares, o tomar el logaritmo! ```r df_gdp <- df_gdp %>% mutate(gdp_million = gdp / 1000000, gdp_log = log(gdp)) head(df_gdp) ``` ``` ## # A tibble: 6 × 9 ## country continent year lifeExp pop gdpPercap gdp gdp_million gdp_log ## <fct> <fct> <int> <dbl> <int> <dbl> <dbl> <dbl> <dbl> ## 1 Afghani… Asia 1952 28.8 8.43e6 779. 6.57e 9 6567. 22.6 ## 2 Afghani… Asia 1957 30.3 9.24e6 821. 7.59e 9 7585. 22.7 ## 3 Afghani… Asia 1962 32.0 1.03e7 853. 8.76e 9 8759. 22.9 ## 4 Afghani… Asia 1967 34.0 1.15e7 836. 9.65e 9 9648. 23.0 ## 5 Afghani… Asia 1972 36.1 1.31e7 740. 9.68e 9 9679. 23.0 ## 6 Afghani… Asia 1977 38.4 1.49e7 786. 1.17e10 11698. 23.2 ``` --- ## Mutar para crear (o cambiar) variables Y si queremos crear una variable que depende del valor de otras? Por ejemplo, creemos una dummy para paÃses africanos y otra para europeos: ```r gapminder %>% mutate(africa = if_else(continent == "Africa", 1, 0), europe = if_else(continent == "Europe", 1, 0)) ``` ``` ## # A tibble: 1,704 × 8 ## country continent year lifeExp pop gdpPercap africa europe ## <fct> <fct> <int> <dbl> <int> <dbl> <dbl> <dbl> ## 1 Afghanistan Asia 1952 28.8 8425333 779. 0 0 ## 2 Afghanistan Asia 1957 30.3 9240934 821. 0 0 ## 3 Afghanistan Asia 1962 32.0 10267083 853. 0 0 ## 4 Afghanistan Asia 1967 34.0 11537966 836. 0 0 ## 5 Afghanistan Asia 1972 36.1 13079460 740. 0 0 ## 6 Afghanistan Asia 1977 38.4 14880372 786. 0 0 ## 7 Afghanistan Asia 1982 39.9 12881816 978. 0 0 ## 8 Afghanistan Asia 1987 40.8 13867957 852. 0 0 ## 9 Afghanistan Asia 1992 41.7 16317921 649. 0 0 ## 10 Afghanistan Asia 1997 41.8 22227415 635. 0 0 ## # … with 1,694 more rows ``` --- ## `arrange()` para ordenar nuestros datos - Veamos cuál era el paÃs con menor esperanza de vida en 1957: ```r gapminder %>% filter(year == 1957) %>% arrange(lifeExp) %>% head(3) # You can use head to restrict the output to any number of observations ``` ``` ## # A tibble: 3 × 6 ## country continent year lifeExp pop gdpPercap ## <fct> <fct> <int> <dbl> <int> <dbl> ## 1 Afghanistan Asia 1957 30.3 9240934 821. ## 2 Sierra Leone Africa 1957 31.6 2295678 1004. ## 3 Angola Africa 1957 32.0 4561361 3828. ``` --- ## `arrange()` para ordenar nuestros datos Y el de mayor? ```r gapminder %>% filter(year == 1957) %>% arrange(desc(lifeExp)) %>% head(3) ``` ``` ## # A tibble: 3 × 6 ## country continent year lifeExp pop gdpPercap ## <fct> <fct> <int> <dbl> <int> <dbl> ## 1 Iceland Europe 1957 73.5 165110 9244. ## 2 Norway Europe 1957 73.4 3491938 11654. ## 3 Netherlands Europe 1957 73.0 11026383 11276. ``` --- ## Ejercicio - Vamos a filtrar y ordenar paÃses a la vez. - Intentad ordenar los paÃses de **más de 100 millones de habitantes** por **esperanza de vida (creciente) en 2002**: - Tenéis ** 1 minuto **. --- ## Ejercicio - Vamos a filtrar y ordenar paÃses a la vez. - Intentad ordenar los paÃses de **más de 100 millones de habitantes** por **esperanza de vida (creciente) en 2002**: ```r gapminder %>% filter(year == 2002, pop > 100000000) %>% arrange(lifeExp) ``` ``` ## # A tibble: 10 × 6 ## country continent year lifeExp pop gdpPercap ## <fct> <fct> <int> <dbl> <int> <dbl> ## 1 Nigeria Africa 2002 46.6 119901274 1615. ## 2 Bangladesh Asia 2002 62.0 135656790 1136. ## 3 India Asia 2002 62.9 1034172547 1747. ## 4 Pakistan Asia 2002 63.6 153403524 2093. ## 5 Indonesia Asia 2002 68.6 211060000 2874. ## 6 Brazil Americas 2002 71.0 179914212 8131. ## 7 China Asia 2002 72.0 1280400000 3119. ## 8 Mexico Americas 2002 74.9 102479927 10742. ## 9 United States Americas 2002 77.3 287675526 39097. ## 10 Japan Asia 2002 82 127065841 28605. ``` --- ## `summarize()` para resumir datos - Muy a menudo, nos interesa calcular medias, medianas, desviaciones estándar, o contar observaciones. - Podemos calcular cualquier tipo de resumen con `summarize()` (o `summarise()`). - Por ejemplo, imaginad que estamos interesados en la media, la mediana y la desviación estándar de la esperanza de vida en 2007: ```r gapminder %>% filter(year == 2007) %>% summarize(exp_mean = mean(lifeExp), exp_median = median(lifeExp), exp_sd = sd(lifeExp)) ``` ``` ## # A tibble: 1 × 3 ## exp_mean exp_median exp_sd ## <dbl> <dbl> <dbl> ## 1 67.0 71.9 12.1 ``` --- ## Grupos de *cosas* - Pero más a menudo, lo que queremos es resúmenes entre grupos! Esto surge todo el tiempo en nuestro trabajo. ```r gapminder %>% group_by(continent) %>% summarize(exp_mean = mean(lifeExp), gdp_mean = mean(gdpPercap)) ``` ``` ## # A tibble: 5 × 3 ## continent exp_mean gdp_mean ## <fct> <dbl> <dbl> ## 1 Africa 48.9 2194. ## 2 Americas 64.7 7136. ## 3 Asia 60.1 7902. ## 4 Europe 71.9 14469. ## 5 Oceania 74.3 18622. ``` - Tened en cuenta que `group_by()` no produce ningún resultado, solo agrupa las variables antes de cualquier operación que venga después (normalmente, `summarize()` --- ## Ejercicio - Podéis encontrar cuál fue la **media** y la **mediana del PIB per cápita** (y el **número de observaciones!**) para **cada uno de los continentes en 1982**? - Tenéis ** 2 minutos **. --- ## Ejercicio ```r gapminder %>% filter(year == 1982) %>% # filtrar para que solo quede 1982 group_by(continent) %>% # agrupar por continente summarize(mean = mean(gdpPercap), # usar summarize median = median(gdpPercap), count = n()) ``` ``` ## # A tibble: 5 × 4 ## continent mean median count ## <fct> <dbl> <dbl> <int> ## 1 Africa 2482. 1324. 52 ## 2 Americas 7507. 6435. 25 ## 3 Asia 7434. 4107. 33 ## 4 Europe 15618. 15323. 30 ## 5 Oceania 18555. 18555. 2 ``` --- ## Referencia: Otras funciones útiles - `distinct()` para seleccionar filas únicas de un dataframe - `top_n()` para filtrar las n primeras observaciones (se puede usar en combinación con `arrange()`) - `if_else()` para cuando queramos hacer algo de forma condicional - `rename()` para cambiar el nombre de las variables en su marco de datos - Todas las funciones: https://dplyr.tidyverse.org/reference/index.html --- ## Regresiones y otras historias - R fue diseñado con la estadÃstica en mente, por lo que hay un montón de funciones integradas para esta clase de tareas. - Intentemos correr una regresión. Para eso nos vamos a quedar con los datos de 1982, y vamos a crear un par de variables. ```r df_regression <- gapminder %>% filter(year == 1982) %>% mutate(africa = if_else(continent == "Africa", 1, 0), europe = if_else(continent == "Europe", 1, 0), americas = if_else(continent == "Americas", 1, 0)) ``` --- ## Regresiones y otras historias - Solemos utilizar `lm` para ejecutar un modelo lineal y` glm` para ejecutar un logit (que significa modelo lineal generalizado). Estos generan un objeto que luego podemos guardar y manipular. ```r my_ols <- lm(lifeExp ~ log(gdpPercap), data = df_regression) ``` --- - El resultado es similar al que se verÃa en Stata. Se puede mostrar en una tabla, imprimirlo, exportarlo y usarlo para gráficos de coeficientes. ```r summary(my_ols) ``` ``` ## ## Call: ## lm(formula = lifeExp ~ log(gdpPercap), data = df_regression) ## ## Residuals: ## Min 1Q Median 3Q Max ## -18.7709 -2.8743 0.4812 3.6039 14.6986 ## ## Coefficients: ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) -0.6505 3.3463 -0.194 0.846 ## log(gdpPercap) 7.4936 0.3990 18.780 <2e-16 *** ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## Residual standard error: 5.762 on 140 degrees of freedom ## Multiple R-squared: 0.7158, Adjusted R-squared: 0.7138 ## F-statistic: 352.7 on 1 and 140 DF, p-value: < 2.2e-16 ``` --- ## Visualizar una regresión (en un dataframe) - Con `broom` ```r library(broom) tidy(my_ols) ``` ``` ## # A tibble: 2 × 5 ## term estimate std.error statistic p.value ## <chr> <dbl> <dbl> <dbl> <dbl> ## 1 (Intercept) -0.650 3.35 -0.194 8.46e- 1 ## 2 log(gdpPercap) 7.49 0.399 18.8 4.46e-40 ``` --- ## Visualizar una regresión (en una tabla) - Con el paquete `modelsummary` podemos creat tablas de regresión fácilmente. ```r library(modelsummary) modelsummary(my_ols, estimate = "{estimate}{stars}", gof_omit = ".*", output = "gt") ```
Model 1
(Intercept)
-0.650
(3.346)
log(gdpPercap)
7.494***
(0.399)
--- ## Visualizar dos (o más) regresiones ```r my_ols2 <- lm(lifeExp ~ log(gdpPercap) + africa + europe + americas, data = df_regression) my_ols3 <- lm(lifeExp ~ log(gdpPercap) + africa + europe + americas + log(pop), data = df_regression) all_models <- list(Simple = my_ols, Continente = my_ols2, Población = my_ols3) ``` --- ## Visualizar dos (o más) regresiones .pull-left[ ```r modelsummary(all_models, estimate = "{estimate}{stars}", output = "gt", gof_omit = ".*", ) ``` ] .pull-right[
Simple
Continente
Población
(Intercept)
-0.650
18.219***
16.332*
(3.346)
(4.042)
(7.045)
log(gdpPercap)
7.494***
5.425***
5.460***
(0.399)
(0.476)
(0.489)
africa
-6.569***
-6.414***
(1.187)
(1.282)
europe
2.812*
2.817*
(1.382)
(1.387)
americas
0.616
0.651
(1.332)
(1.341)
log(pop)
0.096
(0.295)
] --- class: inverse center middle # Preguntas? --- class: center middle # Gracias! ---